<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <base href="../../../" />
    <script src="page.js"></script>
    <link type="text/css" rel="stylesheet" href="page.css" />
</head>

<body>
    <h1>[name]</h1>
    <div>
        <p>
            下記のコードのようにシーンに追加されたオブジェクトはデフォルトで自動的にマトリクスを更新します。
        </p>
        <code>
const object = new THREE.Object3D();
scene.add( object );
			</code> もしくは、シーンに親オブジェクトが追加されると子オブジェクトも自動的に更新されます。
        <code>
const object1 = new THREE.Object3D();
const object2 = new THREE.Object3D();

object1.add( object2 );
scene.add( object1 ); //object1 and object2 will automatically update their matrices
			</code>
    </div>

    <p>
        しかしながら、オブジェクトが静的なものであると分かっている場合は、自動更新を無効にして必要な時だけ、更新することが出来ます。
    </p>

    <code>
object.matrixAutoUpdate = false;
object.updateMatrix();
		</code>

    <h2>BufferGeometry</h2>
    <div>
        <p>
            BufferGeometriesは、情報（頂点の位置、面のインデックス、法線、色、UV、カスタム属性など）をバッファ、 つまり[link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays Typed_arrays](型付の配列)に保存します。 このため、標準的なジオメトリよりも一般的に高速ですが、その反面、作業がやや難しくなっています。
        </p>
        <p>
            BufferGeometriesの更新についてバッファのサイズを変更することができないということは理解しておく必要があります。(これは非常にコストがかかり、基本的には新しいジオメトリを作成するのと同じです）。しかし、バッファの内容を更新することはできます。

        </p>
        <p>
            つまり、BufferGeometry の属性（例えば頂点の数など）が増加することがわかっている場合、 新たに作成される可能性のある頂点を保持するのに十分な大きさのバッファを事前に確保しておく必要があります。 もちろん、これはBufferGeometryの最大サイズが存在することになります。
        </p>
        <p>
            ここでは、レンダリング時に拡張される線の例を使用します。 バッファに500頂点分のスペースを確保しますが、[page:BufferGeometry.drawRange]を使って最初は2つだけ描画します。
        </p>
        <code>
const MAX_POINTS = 500;

// geometry
const geometry = new THREE.BufferGeometry();

// attributes
const positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point
geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );

// draw range
const drawCount = 2; // draw the first 2 points, only
geometry.setDrawRange( 0, drawCount );

// material
const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );

// line
const line = new THREE.Line( geometry, material );
scene.add( line );
			</code>
        <p>
            次に以下のようにして、線上にランダムに点を追加してみましょう。
        </p>
        <code>
const positionAttribute = line.geometry.getAttribute( 'position' );

let x = 0, y = 0, z = 0;

for ( let i = 0; i < positionAttribute.count; i ++ ) {

    positionAttribute.setXYZ( i, x, y, z );

    x += ( Math.random() - 0.5 ) * 30;
    y += ( Math.random() - 0.5 ) * 30;
    z += ( Math.random() - 0.5 ) * 30;

}
			</code>
        <p>
            もし、最初の描画以降に<em>点の数</em>を変更したい場合は、以下のようにしてください。
        </p>
        <code>
line.geometry.setDrawRange( 0, newValue );
			</code>
        <p>
            最初の描画以降に位置データの値を変更したい場合は、needsUpdateをtrueにセットする必要があります。
        </p>
        <code>
positionAttribute.needsUpdate = true; // required after the first render
			</code>

        <p>
            最初の描画以降に位置データの値を変更した場合は、frustum cullingやヘルパーといったエンジンの他の機能がちゃんと機能するようにboundingボリュームを再計算する必要があるかもしれません。
        </p>
        <code>
line.geometry.computeBoundingBox();
line.geometry.computeBoundingSphere();
			</code>

        <p>
           ここ([link:https://jsfiddle.net/t4m85pLr/1/ link])では、あなたのユースケースに合わせることができるアニメーションを表示しています。
        </p>

        <h3>Examples</h3>

        <p>
            [example:webgl_custom_attributes WebGL / custom / attributes]<br /> [example:webgl_buffergeometry_custom_attributes_particles WebGL / buffergeometry / custom / attributes / particles]
        </p>

    </div>

    <h2>Materials</h2>
    <div>
        <p>
            ユニフォームの値(例えば、色やテクスチャや透明度)は自由に変更することが出来ます。 これらの値はフレームごとにシェーダに送られます。
        </p>

        <p>
            GLstateに関連したパラメータ(depthTest, blending, polygonOffsetなど)もいつでも変更出来ます。
        </p>

        <p>
            以下に示すパラメータはランタイム(マテリアルが一度描画された後)には簡単に変更ができません。
        </p>
        <ul>
            <li>ユニフォームの種類や数</li>
            <li>以下の要素の有無
                <ul>
                    <li>texture</li>
                    <li>fog</li>
                    <li>vertex colors</li>
                    <li>morphing</li>
                    <li>shadow map</li>
                    <li>alpha test</li>
                    <li>transparent</li>
                </ul>
            </li>
        </ul>

        <p>
            これらの値を変更するのには新しいシェーダプログラムが必要です、そのためには以下のように設定してください。
        </p>
        <code>material.needsUpdate = true</code>

        <p>
            こうすることで、プログラムはとても遅くなり、フレームレートが不安定になるかもしれないことを覚えておいてください。(特にWindowsでは、シェーダのコンパイルがOpenGLよりもDirectXの方が遅いので、より顕著に現れる可能性があります）。
        </p>

        <p>
            より滑らかな体験を提供するために、明るさ0の光や、白紙のテクスチャ、密度0の霧といった"ダミー"の値を使うことで、これらの変化をある程度模倣することができます。
        </p>

        <p>
            ジオメトリチャンクに使用するマテリアルは自由に変更できますが、オブジェクトをチャンクに分割する方法は変更できません。オブジェクトをどのようにチャンクに分割するからは、表面のマテリアルによって決まります。
        </p>

        <h3>
            ランタイムに異なるマテリアルの設定が必要な場合
        </h3>
        <p>
            マテリアル/チャンクの数が少ない場合は、あらかじめオブジェクトを分割しておくことができます（例：人間の場合は髪/顔/胴体/上着/ズボン、車の場合はフロント/サイド/トップ/ガラス/タイヤ/内装）。


        </p>

        <p>
            数が多い場合（例えば、人の顔はそれぞれ違っている可能性があります）は、顔ごとに異なる外観にするために属性/テクスチャを使用するなど、別の解決策を検討してください。
        </p>

        <h3>Examples</h3>
        <p>
            [example:webgl_materials_car WebGL / materials / car]<br /> [example:webgl_postprocessing_dof WebGL / webgl_postprocessing / dof]
        </p>
    </div>


    <h2>Textures</h2>
    <div>
        <p>
            画像やcanvas、ビデオやデータのテクスチャが変化する場合は、以下のフラグを有効にする必要があります。
        </p>
        <code>
				texture.needsUpdate = true;
			</code>
        <p>描画の対象が自動的に更新されます。</p>

        <h3>Examples</h3>
        <p>
            [example:webgl_materials_video WebGL / materials / video]<br /> [example:webgl_rtt WebGL / rtt]
        </p>

    </div>


    <h2>Cameras</h2>
    <div>
        <p>カメラの位置とターゲットは自動的に更新されます。以下の要素を変更する必要がある場合、projection matrixを再計算する必要があります。</p>
        <ul>
            <li>
                fov
            </li>
            <li>
                aspect
            </li>
            <li>
                near
            </li>
            <li>
                far
            </li>
        </ul>
        <code>
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
			</code>
    </div>
</body>

</html>
